#import  "TVController.h"
#import  <dpsclient/dpsNeXT.h>	// for TimedEntry
#import  <appkit/Application.h>
#import  <appkit/publicWraps.h>
#import  <appkit/Control.h>
#import  <appkit/MenuCell.h>
#import  <objc/NXBundle.h>	/* LocalizedString */
#import  <stdio.h>
#import  <stdlib.h>
#import  <string.h>
#import  <objc/zone.h>
#import  <mach/mach_init.h>
#import  "ToyWin.h"
#import  "ToyView.h"
#import  "Background.h"
#import  "common.h"

#define	 MAXWindows	80

@implementation TVController (WindowManager)

static int winp = 0, showp = 0;
static ToyWin *wintab[MAXWindows];
static DPSTimedEntry teNum;
static Window *backWin;
NXZone *backZone;

- newWindow: (ToyWin *)win
{
	if (winp < MAXWindows)
		wintab[winp++] = win;
	return self;
}

- checkWindow: (ToyWin *)win delete:(BOOL)delflag;
{
	/* Return Value:  nil: No such window,  self: Success */
	int i, j;

	j = -1;
	for (i = 0; i < winp; i++)
		if (wintab[i] == win) {
			j = i;
			break;
		}
	if (j < 0) return nil;
	if (delflag) {
		--winp;
		for (i = j; i < winp; i++)
			wintab[i] = wintab[i + 1];
	}
	return self;
}

- deleteAllWindow: sender
{
	int i, n;

	n = winp, winp = 0;
	for (i = 0; i < n; i++)
		[[wintab[i] window] performClose: sender];
	return self;
}


static void wakeup(DPSTimedEntry te, double now, void *data)
{
	if (showp >= winp) {
		DPSRemoveTimedEntry(teNum);
		showp = 0;
	}else
		[[wintab[showp++] window] orderFront: (id)data];
}

- showAllWindow: sender
{
	if (winp <= 0) return self;
	if (showp > 0) {
		DPSRemoveTimedEntry(teNum);
		showp = 0;
	}else {
		[[wintab[0] window] orderFront: sender];
		teNum = DPSAddTimedEntry(0.8, &wakeup, self, NX_BASETHRESHOLD);
		showp = 1;
	}
	return self;
}

- keyWindow
{
	int i;

	for (i = 0; i < winp; i++)
		if ([[wintab[i] window] isKeyWindow])
			return wintab[i];
	return (winp > 0) ? wintab[winp - 1] : nil;
}

- (BOOL)isOpened: (const char *)newfile
{
	int i;

	for (i = 0; i < winp; i++)
		if (strcmp(newfile, [wintab[i] filename]) == 0) {
			[[wintab[i] window] makeKeyAndOrderFront: self];
			return YES;
		}
	return NO;
}


/****** Backgroung ******/

- cleanBackground: sender
{
	if (backWin != nil) {
		[backWin free];
		backWin = nil;
		NXDestroyZone(backZone);
		[self backWinFront: NO];
		[menuToFront setEnabled: NO];
		[menuClear setEnabled: NO];
	}else
		NXBeep();
	return self;
}

- makeFront: sender
{
	id v;

	if (backWin == nil) {
		NXBeep();
		return self;
	}
	if ([(v = [backWin contentView]) isFront]) /* toggle */
		[v toBehind: self];
	else
		[v toFront: self];
	return self;
}

- backWinFront: (BOOL)flag
{
	const char *title;

	if (flag)
		title = NXLocalizedString("Send to Back", NULL, Background);
	else
		title = NXLocalizedString("Bring to Front", NULL, Background);
	[menuToFront setTitle: title];
	return self;
}

- makeBackground: sender
{
	NXRect	rect, *ir;
	Background *view;
	id	tw, tv;
	commonInfo *cinf;
	int method = [sender selectedTag];
	
	if ((tw = [self keyWindow]) == nil) {
		NXBeep();
		return self;
	}
	tv = [tw toyView];
	if (backWin == nil) {
		[NXApp getScreenSize: &rect.size];
		rect.origin.x = rect.origin.y = 0;
		backZone = NXCreateZone(vm_page_size, vm_page_size, YES);
		view = [[Background allocFromZone: backZone] initFrame: &rect];
		[view setController: self];
		backWin = [view initWinAttr];
		[menuToFront setEnabled: YES];
		[menuClear setEnabled: YES];
	}else
		view = [backWin contentView];
	cinf = [tv commonInfo];
	ir = [tv selectedRect];
	if (ir->size.width > 0.0 && ir->size.height > 0.0) {
		id tmp = [[NXImage alloc] initFromImage:[tv image] rect:ir];
		[view setImage: tmp hasAlpha: cinf->alpha with: method];
		[tmp free];
	}else
		[view setImage: [tv image] hasAlpha: cinf->alpha with: method];
	[backWin display];
	NXPing();
	return self;
}



- print: sender
{
	id	tw;

	if ((tw = [self keyWindow]) == nil)
		NXBeep();
	else
		[tw print:sender];
	return self;
}

- saveAs: sender
{
	ToyWin	*tw;

	if ((tw = (ToyWin *)[self keyWindow]) == nil) {
		NXBeep();
		return self;
	}
	switch ([sender selectedTag]) {
	case 0: [tw saveAsTiff: sender];
		break;
	case 1: [tw saveAsEPS: sender];
		break;
	case 2: [tw saveAs: Type_bmp];
		break;
	case 3: [tw saveAs: Type_gif];
		break;
	case 4: [tw saveAs: Type_ppm];
		break;
	}
	return self;
}

@end
